package wei.qiang.ye.sbspringmvcdemo.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import wei.qiang.ye.sbspringmvcdemo.interceptor.FirstInterceptor;
import wei.qiang.ye.sbspringmvcdemo.interceptor.SecondInterceptor;
import wei.qiang.ye.sbspringmvcdemo.interceptor.ThirdInterceptor;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Configuration
public class SpringMVCConfiguration implements WebMvcConfigurer {
    private Logger logger = LoggerFactory.getLogger(getClass());


    @Bean
    public FirstInterceptor firstInterceptor() {
        return new FirstInterceptor();
    }

    @Bean
    public SecondInterceptor secondInterceptor() {
        return new SecondInterceptor();
    }

    @Bean
    public ThirdInterceptor thirdInterceptor() {
        return new ThirdInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 拦截器一
//        registry.addInterceptor(this.firstInterceptor()).addPathPatterns("/**");
//        // 拦截器二
//        registry.addInterceptor(this.secondInterceptor()).addPathPatterns("/users/current_user");
//        // 拦截器三
//        registry.addInterceptor(this.thirdInterceptor()).addPathPatterns("/**");
    }


    /**
     * 以bean方式添加servlet
     * @return
     */
//    @Bean
//    public ServletRegistrationBean testServlet01() {
//        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(new HttpServlet() {
//            @Override
//            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//                logger.info("[doGet][uri: {}]", req.getRequestURI());
//            }
//
//        });
//        servletRegistrationBean.setUrlMappings(Collections.singleton("/test/01"));
//        return servletRegistrationBean;
//    }

    /**
     * 以bean方式添加filter
     * @return
     */
//    @Bean
//    public FilterRegistrationBean testFilter01() {
//        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(new Filter() {
//            @Override
//            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//                logger.info("[testFilter01]");
//                filterChain.doFilter(servletRequest, servletResponse);
//            }
//
//        });
//        filterRegistrationBean.setUrlPatterns(Collections.singleton("/test/*"));
//        return filterRegistrationBean;
//    }

    /**
     * 以bean方式添加listener
     * @return
     */
//    @Bean
//    public ServletListenerRegistrationBean<?> testListener01() {
//        return new ServletListenerRegistrationBean<>(new ServletContextListener() {
//            @Override
//            public void contextInitialized(ServletContextEvent sce) {
//                logger.info("[testListener01 contextInitialized]");
//            }
//            @Override
//            public void contextDestroyed(ServletContextEvent sce) {
//            }
//        });
//    }


    /**
     * 不推荐使用
     * 坑，OPTIONS 预检查走到拦截器里，会把handler的PreFlightHandler类型认为是HandlerMethod类型
     * 解决跨域问题
     * 配置单个路径的 CORS 配置，可以通过 CorsRegistry#addMapping(String pathPattern) 方法，继续往其中添加 CORS 配置
     * @param registry
     */
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        // 添加全局的 CORS 配置
//        registry.addMapping("/**") // 匹配所有 URL ，相当于全局配置
//                .allowedOrigins("*") // 允许所有请求来源
//                .allowCredentials(true) // 允许发送 Cookie
//                .allowedMethods("*") // 允许所有请求 Method
//                .allowedHeaders("*") // 允许所有请求 Header
//                .maxAge(1800L); // 有效期 1800 秒，2 小时
//    }


    /**
     * 建议使用
     * 解决跨域问题
     * @return
     */
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        // 创建 UrlBasedCorsConfigurationSource 配置源，类似 CorsRegistry 注册表
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 创建 CorsConfiguration 配置，相当于 CorsRegistration 注册信息
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Collections.singletonList("*")); // 允许所有请求来源
        config.setAllowCredentials(true); // 允许发送 Cookie
        config.addAllowedMethod("*"); // 允许所有请求 Method
        config.setAllowedHeaders(Collections.singletonList("*")); // 允许所有请求 Header
        // config.setExposedHeaders(Collections.singletonList("*")); // 允许所有响应 Header
        config.setMaxAge(1800L); // 有效期 1800 秒，2 小时
        source.registerCorsConfiguration("/**", config);
        // 创建 FilterRegistrationBean 对象
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(
                new CorsFilter(source)); // 创建 CorsFilter 过滤器
        bean.setOrder(0); // 设置 order 排序，为避免麻烦请设置在最前
        return bean;
    }


    /**
     *
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 增加 XML 消息转换器
        Jackson2ObjectMapperBuilder xmlBuilder = Jackson2ObjectMapperBuilder.xml();
        xmlBuilder.indentOutput(true);
        converters.add(new MappingJackson2XmlHttpMessageConverter(xmlBuilder.build()));

        // 创建 FastJsonHttpMessageConverter 对象
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        // 自定义 FastJson 配置
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(Charset.defaultCharset()); // 设置字符集
        fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); // 剔除循环引用
        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
        // 设置支持的 MediaType
        fastJsonHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON));
        // 添加到 converters 中
        converters.add(0, fastJsonHttpMessageConverter); // 注意，添加到最开头，放在 MappingJackson2XmlHttpMessageConverter 前面
    }


}
